#include "ResourceManager.h"
#include <stdio.h>
#include "platforms.h"
#include <string.h>
#include "FileManager.h"

ResourceManager* ResourceManager::s_instance = NULL;

ResourceManager::ResourceManager(void)
{
	m_model = NULL;
	m_texture = NULL;
	m_shader = NULL;
	m_numOfModel = 0;
	m_numOfTexture = 0;
	m_numOfShader = 0;
}

ResourceManager::~ResourceManager(void)
{
	for (int i = 0; i < m_numOfModel; i++)
	{
		SAFE_DEL(m_model[i]);
	}
	
	SAFE_DEL(m_model);

	for (int i = 0; i < m_numOfTexture; i++)
	{
		SAFE_DEL(m_texture[i]);
	}

	SAFE_DEL(m_texture);

	for (int i = 0; i < m_numOfShader; i++)
	{
		SAFE_DEL(m_shader[i]);
	}
	
	SAFE_DEL(m_shader);
}

void ResourceManager::Init(const char* fileName)
{
	FileManager *fileManager = FileManager::GetInstance();
	FILE *pFile = fileManager->Open(fileName, "r");

	if (pFile == NULL)
	{
		LOGI("Doc file %s loi.\n", fileName);
		return;
	}

	else
	{
		char id[MAX_10];
		char path[MAX_256];

		fscanf(pFile, "#Models: %d\n", &m_numOfModel);

		m_model = new Model*[m_numOfModel];

		for (int i = 0; i < m_numOfModel; i++)
		{
			fscanf(pFile, "ID: %s\n", id);
			fscanf(pFile, "Path: %s\n", path);
			m_model[i] = new Model();
			m_model[i]->Init(path, id);
		}

		fscanf(pFile, "#Textures: %d\n", &m_numOfTexture);

		m_texture = new Texture*[m_numOfTexture];

		int numOfTexture2D, numOfTextureCube;
		char wrap[100];
		int tiling;

		fscanf(pFile, "Texture2D: %d\n", &numOfTexture2D);
	
		for (int i = 0; i < numOfTexture2D; i++)
		{
			fscanf(pFile, "ID: %s\n", id);
			fscanf(pFile, "Path: %s\n", path);
			fscanf(pFile, "Wrap: %s\n", wrap);

			if (strcmp(wrap,"REPEAT") == 0)
			{
				tiling = GL_REPEAT;
			}

			else if (strcmp(wrap,"CLAMP") == 0)
			{
				tiling = GL_CLAMP_TO_EDGE;
			}

			m_texture[i] = new Texture();
			m_texture[i]->Init(path, GL_TEXTURE_2D, tiling, id);
		}

		fscanf(pFile, "TextureCube: %d\n", &numOfTextureCube);
		{
			for (int i = numOfTexture2D; i < numOfTexture2D + numOfTextureCube; i++)
			{
				fscanf(pFile, "ID: %s\n", id);
				fscanf(pFile, "Path: %s\n", path);
				fscanf(pFile, "Wrap: %s\n", wrap);

				if (strcmp(wrap,"REPEAT") == 0)
				{
					tiling = GL_REPEAT;
				}

				else if (strcmp(wrap,"CLAMP") == 0)
				{
					tiling = GL_CLAMP_TO_EDGE;
				}

				m_texture[i] = new Texture();
				m_texture[i]->Init(path, GL_TEXTURE_CUBE_MAP, tiling, id);
			}
		}
		
		fscanf(pFile, "#Shaders: %d\n", &m_numOfShader);

		m_shader = new Shader*[m_numOfShader];

		int numOfState;
		char stateString[100];
		int state;
		char pathVs[MAX_256];
		char pathFs[MAX_256];

		for (int i = 0; i < m_numOfShader; i++)
		{
			fscanf(pFile, "ID: %s\n", id);
			fscanf(pFile, "Path: %s %s\n", pathVs, pathFs);

			m_shader[i] = new Shader();
			m_shader[i]->Init(pathVs, pathFs, id);

			fscanf(pFile, "States: %d\n", &numOfState);
			for (int j = 0; j < numOfState; j++)
			{
				fscanf(pFile, "State: %s\n", stateString);

				if (strcmp(stateString, "DEPTH") == 0)
				{
					state = GL_DEPTH_TEST;
				}

				else if (strcmp(stateString, "CULLING") == 0)
				{
					state = GL_CULL_FACE;
				}
				
				else if (strcmp(stateString, "BLEND") == 0)
				{
					state = GL_BLEND;
				}

				m_shader[i]->AddState(state);
			}
		}
	}

	fclose(pFile);
}

Model* ResourceManager::GetModelById(const char* id)
{
	Model *model = NULL;
	for (int i = 0; i < m_numOfModel; i++)
	{
		if (strcmp(m_model[i]->GetID(), id) == 0)
		{
			model = m_model[i];
		}
	}
	return model;
}

Texture* ResourceManager::GetTextureById(const char* id)
{
	Texture *texture = NULL;
	for (int i = 0; i < m_numOfTexture; i++)
	{
		if (strcmp(m_texture[i]->GetID(), id) == 0)
		{
			texture = m_texture[i];
		}
	}
	return texture;
}

Shader* ResourceManager::GetShaderById(const char* id)
{
	Shader *shader = NULL;
	for (int i = 0; i < m_numOfShader; i++)
	{
		if (strcmp(m_shader[i]->GetID(), id) == 0)
		{
			shader = m_shader[i];
		}
	}
	return shader;
}

ResourceManager* ResourceManager::GetInstance()
{
	if (s_instance == NULL)
	{
		s_instance = new ResourceManager();
	}
	return s_instance;
}

void ResourceManager::Destroy()
{
	if (s_instance != NULL)
	{
		SAFE_DEL(s_instance);
	}
}